Closed zx9597446 closed 6 months ago
sorry, forgot something:
i tried the following with the code from this repository.
make menuconfig
-> Advanced configuration options
-> Toolchain options
-> Select Build/Install gccgo
Exit with saving.
make V=s
After this process finished, there should be a binary under staging_dir/toolchain-mips*/bin
.
Unfortunately there is no gccgo.
Where is my fault?
OK, finally I could build gccgo, here's what I do:
Exit with saving.
make V=s
Now I need to figure out how to cross compile go binary.
EDIT: I forgot select eglibc.
i got my go-code running on OpenWrt.
You have to select eglibc
instead of uclibc
because of uclibc
is not able to compile libgo which is necessary for the binaries.
make menuconfig
-> Advanced configuration options
-> Toolchain options
-> C library implementation
-> Use eglibc
You also have to compile the firmware with this settings, which will be done automatically.
The new firmware includes the eglibc libraries and can be found under bin/ar71xx-eglibc/openwrt-ar71xx-generic-carambola2-squashfs-sysupgrade.bin
. Flash it via web-interface or on the shell.
With this preparations done, you can start to compile your go-code
Add an alias with your toolchain path information. This keeps it easy to call gccgo.
alias mips_gccgo='mips-openwrt-linux-gccgo -Wl,-R,/home/andre/development/carambola2/staging_dir/toolchain-mips_34kc_gcc-4.8.0_eglibc-2.19//lib/gcc/mips-openwrt-linux-gnu/4.8.3 -L /home/andre/development/carambola2/staging_dir/toolchain-mips_34kc_gcc-4.8.0_eglibc-2.19/lib'
By now i found no way to use libgo non-static. So every binary has to contain an included static version , which results in a significant bigger size.
My go-code to test
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
compile using the following command
mips_gccgo -Wall -o helloworld_static_libgo helloworld.go -static-libgo
As i told you, this results in a fairly large binary.
-rwxr-xr-x 1 andre users 2.5M Feb 4 09:21 helloworld_static_libgo
but runs perfectly
root@OpenWrt:~# ./helloworld_static_libgo
hello world
Currently i'm working on building a more complex project with some dependent libraries like gorilla_mux and mysql. The sql-driver is a tricky part, can't get it compiled by now.
@zx9597446 @edi-design @GeertJohan
When I do make V=s
, I got some errors. Did you know what's wrong?
cc1: all warnings being treated as errors
Makefile:3120: recipe for target 'proc.lo' failed
make[8]: *** [proc.lo] Error 1
make[8]: Leaving directory '/home/akagi201/openwrt-go/build_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final/mips-openwrt-linux-uclibc/libgo'
Makefile:3889: recipe for target 'all-recursive' failed
make[7]: *** [all-recursive] Error 1
make[7]: Leaving directory '/home/akagi201/openwrt-go/build_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final/mips-openwrt-linux-uclibc/libgo'
Makefile:2225: recipe for target 'all' failed
make[6]: *** [all] Error 2
make[6]: Leaving directory '/home/akagi201/openwrt-go/build_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final/mips-openwrt-linux-uclibc/libgo'
Makefile:11743: recipe for target 'all-target-libgo' failed
make[5]: *** [all-target-libgo] Error 2
make[5]: Leaving directory '/home/akagi201/openwrt-go/build_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final'
Makefile:857: recipe for target 'all' failed
make[4]: *** [all] Error 2
make[4]: Leaving directory '/home/akagi201/openwrt-go/build_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final'
Makefile:75: recipe for target '/home/akagi201/openwrt-go/build_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final/.built' failed
make[3]: *** [/home/akagi201/openwrt-go/build_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final/.built] Error 2
make[3]: Leaving directory '/home/akagi201/openwrt-go/toolchain/gcc/final'
toolchain/Makefile:86: recipe for target 'toolchain/gcc/final/compile' failed
make[2]: *** [toolchain/gcc/final/compile] Error 2
make[2]: Leaving directory '/home/akagi201/openwrt-go'
toolchain/Makefile:85: recipe for target '/home/akagi201/openwrt-go/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/stamp/.toolchain_install' failed
make[1]: *** [/home/akagi201/openwrt-go/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/stamp/.toolchain_install] Error 2
make[1]: Leaving directory '/home/akagi201/openwrt-go'
/home/akagi201/openwrt-go/include/toplevel.mk:169: recipe for target 'world' failed
make: *** [world] Error 2
@Akagi201 I never see this error before.
@edi-design
I have built hello world with gccgo, but not test it.
I'm working on cross compile complex go program using go build
, I follow this
https://github.com/golang/go/wiki/GccgoCrossCompilation
but still , there are some tricks here, it's not that easy.
I have no clue. The errors show that the recipes failed, but afaik not WHY the failed. Although I see "uClibc" mentioned, and libgo cannot compile with uClibc. You need to select eglibc in the make menu.
@Akagi201 i agree with @GeertJohan you have to select eglibc as i mentioned in my last post.
make menuconfig
-> Advanced configuration options
-> Toolchain options
-> C library implementation
-> Use eglibc
@zx9597446
i used nearly the same instructions but did not tried to link the go build command yet.
My current problem is, that i have to build every go-file and had to link it to the next build step because of their dependencies. Progress has been made, but it is still a long-time processing by hand.
maybe linking xgo
and go build is a solution. i will give it a try. thanks.
@edi-design @GeertJohan That's the matter. Thanks.
@edi-design Could you strip the hello program and then run it on the router. I want to know the result. Thanks.
@Akagi201 what do you mean by strip?
@edi-design I mean use openwrt-go/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_eglibc-2.19/bin/mips-openwrt-linux-strip helloworld_static_libgo
to reduce the binary size, and then run it on the openwrt router. In my test, the size reduced to 1.2mb. I don't have a openwrt nearby, so I hope you can help.
mips-openwrt-linux-strip helloworld_static_libgo
ls -lah
-rwxr-xr-x 1 andre users 1.1M Feb 6 08:15 helloworld_static_libgo
reduced the size to its half.
root@OpenWrt:~# ./helloworld_static_libgo
no debug info in ELF executable errno -1
fatal error: no debug info in ELF executable
the first attempt failed. i will give it another try later that day. maybe i'm missing something.
What I have enabled is:
Advanced configuration options > Toolchain options:
Base system:
libgo
libgo
can become quite large, it contains the complete std library. This could become a problem when the image is too large to flash, depending on the device you're flashing to. My device could only be flashed with an image with a max size being half the size of the ROM storage.
What can help is to only compile libgo, but not put it in the image. Then after the installation copy libgo to the device manually. Or find a way to compile your go program fully static, so it won't need libgo at all.
@edi-design Go programs cannot run without debug information. That's strange, but sadly true.
@southwolf thanks for this information. so by now there should be no chance to get smaller binaries.
@edi-design Well, I had some more tests, showing that on x86/x64, stripping golang executables works fine, but on ARM/MIPS, where file size is a key point, golang executables cannot run without debug information. What I shame.
@southwolf thanks for the info!
Hi All,
I really want to be able to run the go app on an open mesh device running stock open mesh firmware so it still works with cloudtrax.
From what I'm reading it requires eglibc firmware and not uclibc which is what the stock open mesh firmware is running.
Is anyone able to confirm if go binaries can actually run on uclibc firmware or not please?
Cheers Paul
can anyone build libgo with musl-libc? BTW, how about waiting linaro gcc 5.1 since it has better golang support
@wongsyrone Unfortunately, musl is missing {make,get,set}context() as well http://www.openwall.com/lists/musl/2013/07/25/13 So I guess the only chance is gcc 5.1 ...
Hi. My router is using uClibc, which doesn't have the make/get/setcontext(),how to solve?
The following error occurred during compilation:
/home/vare/openwrt-go/build_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04/libgo/runtime/proc.c:244:2: error: implicit declaration of function 'setcontext' [-Werror=implicit-function-declaration]
setcontext(&newg->context);
^
/home/vare/openwrt-go/build_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04/libgo/runtime/proc.c: In function 'runtime_mcall':
/home/vare/openwrt-go/build_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04/libgo/runtime/proc.c:279:3: error: implicit declaration of function 'getcontext' [-Werror=implicit-function-declaration]
getcontext(&gp->context);
^
/home/vare/openwrt-go/build_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04/libgo/runtime/proc.c: In function 'runtime_newextram':
/home/vare/openwrt-go/build_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04/libgo/runtime/proc.c:1111:2: error: implicit declaration of function 'makecontext' [-Werror=implicit-function-declaration]
makecontext(&mp->g0->context, kickoff, 0);
^
cc1: all warnings being treated as errors
make[8]: * [proc.lo] Error 1
make[8]: Leaving directory `/home/vare/openwrt-go/build_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final/mipsel-openwrt-linux-uclibc/libgo'
make[7]: * [all-recursive] Error 1
make[7]: Leaving directory/home/vare/openwrt-go/build_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final/mipsel-openwrt-linux-uclibc/libgo' make[6]: **\* [all] Error 2 make[6]: Leaving directory
/home/vare/openwrt-go/build_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final/mipsel-openwrt-linux-uclibc/libgo'
make[5]: [all-target-libgo] Error 2
make[5]: Leaving directory`/home/vare/openwrt-go/build_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final'
make[4]: \ [all] Error 2
make[4]: Leaving directory /home/vare/openwrt-go/build_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final' make[3]: *** [/home/vare/openwrt-go/build_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/gcc-linaro-4.8-2014.04-final/.built] Error 2 make[3]: Leaving directory
/home/vare/openwrt-go/toolchain/gcc/final'
make[2]: * [toolchain/gcc/final/compile] Error 2
make[2]: Leaving directory `/home/vare/openwrt-go'
make[1]: * [/home/vare/openwrt-go/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/stamp/.toolchain_install] Error 2
make[1]: Leaving directory`/home/vare/openwrt-go'
make: *\ [world] Error 2
http://git.uclibc.org/uClibc/commit/?id=a8dc90eaaa5e6474beac828558d969b1aafee4af
I found a uClibc patch about add context.
@varequan Just modified the 'toolchain/uClibc/config/common' file and add new line like this 'HAS_XXX_CONTEXT=y'
Is there any body can help me to solve below gcc go compilation issue ?
/mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02-final/./gcc/gccgo -B/mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02-final/./gcc/ -Os -pipe -mno-branch-likely -mips32r2 -mtune=1004kc -mdsp -fno-caller-saves -fhonour-copts -Wno-error=unused-but-set-variable -msoft-float -L ../mipsel-openwrt-linux-uclibc/libgo -L ../mipsel-openwrt-linux-uclibc/libgo/.libs -L/mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/staging_dir/target-mipsel_1004kc+dsp_uClibc-1.0.12/usr/lib -L/mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/staging_dir/target-mipsel_1004kc+dsp_uClibc-1.0.12/lib -L/mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/staging_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/usr/lib -L/mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/staging_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/lib -o go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/build.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/clean.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/context.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/discovery.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/env.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/fix.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/fmt.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/generate.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/get.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/go11.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/help.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/http.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/list.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/main.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/pkg.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/run.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/signal.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/signal_unix.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/test.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/testflag.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/tool.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/vcs.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/version.go /mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/build_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/gcc-linaro-5.3-2016.02/gotools/../libgo/go/cmd/go/vet.go ../mipsel-openwrt-linux-uclibc/libgo/zstdpkglist.go zdefaultcc.go
/mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/staging_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/mipsel-openwrt-linux-uclibc/bin/ld: cannot find crt1.o: No such file or directory
/mnt/sdb/home/tymon/openwrt/git/pandorabox/14.09/mtk/mt7621-9395ae/staging_dir/toolchain-mipsel_1004kc+dsp_gcc-5.3-linaro_uClibc-1.0.12/mipsel-openwrt-linux-uclibc/bin/ld: cannot find crti.o: No such file or directory
@wongsyrone I am using GCC-Linaro 5.3.1 to build GO language(and also libgo) with uClibc-1.0.12, ongoing now!
To be honest, although you can compile all things correctly, the concern about binary size and speed still exists, which makes cross-compiling golang programs pointless. The debugging info and statically linking are two deal killer. Please correct me if the situation changed.
I know this thread is quite old, but I have investigated better languages (than C/C++) for OpenWrt MIPS several times over the last few years and I always come up with the same two options: 1) Nim (https://www.nim-lang.org): capable but complicated. Transpiles to C, and has a specific mips transpilation variant. A serial port to network server application binary in around 200K stripped. Large, but by no means a deal breaker. 2) Lua: simple and fast, but the libraries available always seem to be quite buggy (especially for 5.1 which is the default version as of LEDE 18.06). The interpreter is around 200K. Generally it is already installed because Luci requires it.
The other options I've considered: GO: Binaries WAY too big Rust: Does not compile to mips, executables too big (size tested on x86) Python: too slow, and interpeter/binaries too large. Generally difficult to get working. Node: Interpreter too large (around 5MB) PHP: Actually works quite well, but can be memory hungry. Not suited to system programming tasks.
I find GO to be the best option for building for OpenWrt, all you need is export GOARCH=mips & export GOMIPS=softfloat and a go helloworld will run perfect.
Unfortunately CGO does not work as easy, and most complex go native programs will use code that is not compatible with mips. So unless your willing to find clean libraries or write your own you'll have trouble.
I use an external HDD on the OpenWRT, so binary size is not an issue.
hello, I want to build an golang program runs on openwrt(MIPS) router, I searched google, found your great job, I'm new to openwrt, so the question maybe dumb: