When I use flag package
// main.go
import (
...
"flag"
)
func main() {
...
flag.Parse()
switch flag.Arg(0) {
case "doSomething1":
...
case "doSomething2":
...
}
}
If doSomething1 argument print some error message for me, whatever I fix the source code, it can not remove the old error code and compile again.
// command-line
# go build ./main.go
# ./main doSomething1
# error doSomething1 can not work
-- I fix my code
# ./main doSomething1
# error doSomething1 can not work
-- the error message also show me again
-- I have to delete main and build again
# rm ./main
# go build ./main.go
# ./main.go doSomething1
# doSomething1 now can work
Go is a compiled language. When you run go build, it will compile your sources and create an executable binary. This is what you run when executing ./main doSomething1.
When you change your sources and run ./main doSomething1, you are not compiling again, you just run the previously built (and unchanged) binary.
To quickly test changes, use go run instead:
go run main.go doSomething1
That will always compile your sources, build a binary in a temporary folder, launch it and clear it once your app exits.
For details, see What does go build build?
Related
Is there a way to configure/direct go build, go test etc to report file locations using absolute paths? I frequently run go build from my editor (which parses the output) and it would be convenient if the current working directory of the go build process and the editor itself did not need to match.
So far, the only solution I've found is to wrap go build in a script that determines absolute paths to files, then immediately cds to a temporary directory before invoking go build with the realpath'd original arguments.
Creating a temporary directory and cd'ing to it just to trick the go tools seems like a bizarre workaround, so I'm wondering if there's a more direct solution.
Is there a way to configure the go tools to report absolute paths besides wrapping them and cding to random directories?
Suppose that my GOPATH is /go and that I have the following file.
// /go/src/nonexistent-website.com/example-2019-10-26/main.go
package main
import (
"fmt"
)
func main() {
fmt.Println("hi")
}
Suppose I intentionally introduce an error in this file.
// /go/src/nonexistent-website.com/example-2019-10-26/main.go
package main
// import (
// "fmt"
// )
func main() {
fmt.Println("hi")
}
go build main.go reports the following error:
/go/src/nonexistent-website.com/example-2019-10-26$ go build main.go
# command-line-arguments
./main.go:9: undefined: fmt in fmt.Println
2
go build ... still reports ./main.go as the path to the file if given an absolute path
/go/src/nonexistent-website.com/example-2019-10-26$ go build `realpath main.go`
# command-line-arguments
./main.go:9: undefined: fmt in fmt.Println
2
go build seems to produce paths relative to the directory it was invoked from:
These are the paths that go build produces when directed to cd to the root directory first.
/go/src/nonexistent-website.com/example-2019-10-26$ (a=`realpath main.go` && cd / && go build $a)
# command-line-arguments
go/src/nonexistent-website.com/example-2019-10-26/main.go:9: undefined: fmt in fmt.Println
2
It's possible to coax go build into emitting absolute paths by cd-ing to a directory that's guaranteed to be fresh
/go/src/nonexistent-website.com/example-2019-10-26$ (a=`realpath main.go` && cd `mktemp -d` && go build $a)
# command-line-arguments
/go/src/nonexistent-website.com/example-2019-10-26/main.go:9: undefined: fmt in fmt.Println
2
Is there a way to configure the go tools to report absolute paths besides wrapping them and cding to random directories?
No.
I’m trying to build a libtest.a with Go1.11.4 using cgo under linux/mips64le.
I make a simple Go file, this is test.go code:
package main
import(
“C”
“fmt”
)
func main() {
}
//export hello
func hello(){
fmt.Println(“Hello World”)
}
and I did:
CGO_ENABLED=1 go build -o libtest.a -buildmode=c-archive test.go
I get these very non-descriptive errors:
# internal/race
flag provided but not defined: -shared
usage: compile [options] file.go...
(... many options such like -K, -L, -M etc.)
# internal/cpu
(...following like above)
# errors
# runtime/internal/sys
# math/bits
# runtime/internal/atomic
# sync/atomic
# math
# unicode/utf8
# unicode
# runtime/cgo
How can I do it? I can not use cgo under mips64le? best regards
On my Mac, I build with:
GOOS=linux GOARCH=mips64le go build
It works well under mips64le(OS:NeoKylin).
Directory layout:
~ cd $GOPATH
~ tree src/simple
src/simple
└── main
├── main.go
└── other.go
main.go:
package main
import "fmt"
func main() {
fmt.Println("This is in main. calling somefunc...")
somefunc()
fmt.Println("done. bye :)")
}
other.go:
package main
import "fmt"
func somefunc() {
fmt.Println("This is in somefunc in other.go")
}
This works fine with go build:
~ cd $GOPATH/src/simple/main/
~ go build
~ ./main
This is in main. calling somefunc...
This is in somefunc in other.go
done. bye :)
From within the GoLand IDE, If I run, I get:
main/main.go:7:2: undefined: somefunc
Normally, there is editor highlighting of all syntax errors. The somefunc call is treated as valid syntax in the editor but when I run it doesn't work. I can even cmd-click into the function to jump to the definition.
This is with GoLand 2018.2.3 and go version go1.11
In GoLand create a Run Configuration Run -> Edit Configurations based on Go Build template and set
Name: Build (or whatever you like)
Run kind: Directory
Directory: /Users/gopher/go/src/simple/main/
^^^^^^
Run after build: checked
Working directory: /Users/gopher/go/src/simple
Change /Users/gopher/go/ part accordingly, to match your actual path of $GOPATH
And then Run -> Build the project
This is in main. calling somefunc...
This is in somefunc in other.go
done. bye :)
Process finished with exit code 0
in my library code I have a bunch of static_asserts. I want to test if they fire under the expected conditions.
I would like to write a range of test files and
ensure that they fail to compile
check the output of the compilation attempt for the expected message from the static assert
Does anyone know how to do that with cmake?
AFAICT, try_compile is not the answer, because it is executed while running cmake. I need these checks to be executed during make.
You could set up a "nested" project for these tests, configure it as part of your CMake run and then build it using cmake --build; something like this:
Your normal CMakeLists.txt:
# ...
execute_process(
COMMAND ${CMAKE_COMMAND} path/to/test/project
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/TestProject
)
add_test(
NAME StaticAsserts
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/TestProject
COMMAND ${CMAKE_COMMAND} --build .
)
# ...
Of course, the test command could actually be a wrapper script running cmake --build internally and processing its output.
As an alternative, you could move the configuration of the nested project into the test as well, perhaps using CTest to drive the configure & build.
After several more experiments, this is what I am doing now:
add_executable(
fail_test
EXCLUDE_FROM_ALL
fail_test.cpp
)
add_custom_command(OUTPUT fail_test.out
COMMAND ${CMAKE_MAKE_PROGRAM} fail_test > ${CMAKE_CURRENT_BINARY_DIR}/fail_test.out 2>&1 || true
COMMAND grep "int i = row.alpha" ${CMAKE_CURRENT_BINARY_DIR}/fail_test.out > /dev/null
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fail_test.cpp
COMMENT "fail_test"
)
add_custom_target(test_constraints DEPENDS fail_test.out COMMAND true)
This is what it does:
Create a target for compiling the code that is supposed to fail at compile time. Exclude this target from the default build so that it does not create a mess.
Add a custom command that calls make for this fail-target, pipes the compiler spew into a file, ignores the result code and then greps for the expected compiler message that indicates that the compilation failed due to the expected reason.
Make the custom command depend on the source file, so that the compilation is tested again when the source file is ended.
Add the custom command as dependency to a custom target.
Of course, for more tests, steps 1, 2 and 4 would go into a function.
So now I can call
make test_constraints
to test if the stuff I want to fail compiling actually does so. And if something does not fail as expected, I can even call
make fail_test
to tune the test or its basis until it fails correctly.
For platform independence, the custom command will probably have to be adjusted. Suggestions welcome.
Add this to your CMakeLists.txt:
include(CTest)
# Test that code is NOT able to compile
function(TestStaticCheck TEST_NAME)
add_executable(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_NAME}.cpp)
target_link_libraries(${TEST_NAME} MyLibrary)
add_test(NAME ${TEST_NAME}
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${TEST_NAME}
)
set_tests_properties(${TEST_NAME} PROPERTIES WILL_FAIL TRUE)
endfunction()
TestStaticCheck(TestFoo)
Then put this in TestFoo.cpp in the same directory as your CMakeLists.txt:
int main()
{
// Code that should NOT compile
}
I have just put together a Go package that is going to be a part in a fairly large system with a lot of shared packages. I was able to get it to compile by writing its Makefile such that the compiler is called with -I flags:
include $(GOROOT)/src/Make.inc
TARG=foobar
GOFILES=\
foobar.go\
foobar:
$(GC) -I$(CURDIR)/../intmath -I$(CURDIR)/../randnum foobar.go
include $(GOROOT)/src/Make.pkg
It compiles just fine, and being a good boy, I wrote a comprehensive set of tests. However, when I try to run the tests with gotest, I get a compile error:
$ gotest
rm -f _test/foobar.a
8g -o _gotest_.8 foobar.go foobar_test.go
foobar.go:4: can't find import: intmath
make: *** [_gotest_.8] Error 1
gotest: "C:\\msys\\bin\\sh.exe -c \"gomake\" \"testpackage\" \"GOTESTFILES=foobar_test.go\"" failed: exit status 2
So, the Go file itself will compile when I use the -I flags to tell it where to find the intmath and randnum packages, but gotest doesn't seem to use the Makefile.
Answering peterSO's question:
foobar.go's import section looks like this:
import (
"intmath"
"randnum"
"container/vector"
)
And the compile works fine as long as I have the -I flags going to the compiler. I have tried to use relative paths, like this:
import (
"../intmath"
"../randnum"
"container/vector"
)
but that just doesn't seem to work.
EDIT: answering further peterSO questions:
GOROOT is set to C:\Go the directory where I have all of the Go stuff -- aside from my source code -- installed. I was expecting the relative path to be relative to the directory in which the source file lives.
My source tree looks like this:
server/
foobar/
randnum/
intmath/
So, while I am open to a different, more Go-idiomatic directory structure, my instinct is to arrange them as peers.
Is there some way that I can nudge gotest into compiling foobar.go with the needed flags?
Create the Windows source code directory structure:
C:\server
C:\server\foobar
C:\server\intnum
For intnum.go:
package intnum
func IntNum() int {
return 42
}
Makefile:
include $(GOROOT)/src/Make.inc
TARG=server/intnum
GOFILES=\
intnum.go\
include $(GOROOT)/src/Make.pkg
Run:
$ cd c/server/intnum
$ make install
For foobar.go:
package foobar
import (
"math"
"server/intnum"
)
func FooBar() float64 {
return float64(intnum.IntNum()) * math.Pi
}
Makefile:
include $(GOROOT)/src/Make.inc
TARG=server/foobar
GOFILES=\
foobar.go\
include $(GOROOT)/src/Make.pkg
Run:
$ cd /c/server/foobar
$ make install
After the install, the intnum.a and foobar.a package files will be in the $GOROOT\pkg\windows_386\server (C:\Go\pkg\windows_386\server) directory`.