Error building Go project with /cmd structure (multiple entry points) - go

Here is the directory structure of my project (~/go/src/bitbucket.org/a/b):
├── cmd
│   ├── c
│   │   └── main.go
│   └── d
│   └── main.go
├── config
│   ├── config.go
│   ├── default.json
│   └── development.json
├── go.mod
├── go.sum
├── log
│   └── log.go
├── main.go
I need to compile 2 binaries (one for each module in cmd/).
I have tried running GO111MODULE=on go build ./cmd/c from project root (~/go/src/bitbucket.org/a/b). It silently finishes without doing anything.
I also tried running GO111MODULE=on go build -o test ./cmd/c. It created 29kb test file. When i add execution rights to it and run, it finishes with error:
./test: 2: ./test: Syntax error: newline unexpected
I have tried using go 1.12.5 and go 1.11.10.
Also when i put main.go file from any of the cmd directories to project root directory and build, the compiler builds it just fine (binary file size is ~33mb).
Is it possible to use 2 compiler entry points in a single project?

You can use go install ./... and it will create the executables in $GOPATH/bin directory if you are looking to get the executables
And regarding the multiple compiler entry points, you can. You can build using go build ./cmd/c ./cmd/d . but you cannot get the executables as per the GO Documentation -o can be only used in the case of single package. Instead you can write a makefile to get all the executables with a single make target.
And regarding the error that you are seeing, I would need more information. When I tried to build a sample application, everything works fine. I am not using GO111MODULE flag though.
go build gives me stackoverflow executable
go build -o test ./cmd/c gives me test executable
go build ./cmd/c gives me c executable
For your convenience I uploaded the project to github repo

Related

Is there a way to run a Go module from another directory

I have the following project structure, outside of GOPATH.
. // Project root
├── Dockerfile
├── .env
├── README.md
└── src
├── main.go
├── go.mod
├── go.sum
├── internal
│   ├── somepackage
│   │   ├── main.go
│   │   └── types.go
│   ├── someother
│   │   ├── main.go
│   │   ├── oauth.go
│   │   └── types.go
│   └── models
│   └── main.go
└── pkg
   ├── somepackage
   │   └── main.go
   └── anotherpackage
   └── main.go
I want to run my Go module code located in the src directory.
When I cd into the src directory and go run . or go build . my code, it works perfectly.
When I stand at the root of my project, I am unable to run go run ./src or go build ./src. I get the following error.
src/service.go:8:2: cannot find package "web-service/internal/auth" in any of:
/usr/lib/go/src/web-service/internal/auth (from $GOROOT)
/home/miloertas/Packages/go/src/web-service/internal/auth (from $GOPATH)
src/endpoints.go:3:8: cannot find package "web-service/internal/handlers" in any of:
/usr/lib/go/src/web-service/internal/handlers (from $GOROOT)
/home/miloertas/Packages/go/src/web-service/internal/handlers (from $GOPATH)
It's important that my source code remains in this src directory.
It is equally important that I am able to run and build my code from the root of my project (For example the .env file is located at the root of the repository).
I am therefore looking for a way to run or build my code in the src directory from the root of my project.
I tried moving the go.mod at the root of the project and running and ran go run ./src but this causes issues of its own:
The go command is now unable to locate all the sub-packages in internal and pkg
VSCode is now lost and executing tests is impossible for some reasons (Mainly because all sub-packages are not found).
Since Go 1.18, it's now possible to achieve this with Go workspaces.
Using the following directory structure
parent-dir/
└─ go.work
hello-world/
├─ go.mod
└─ main.go
You can run the hello-world module from the parent-dir using go run hello-world.
go.work
go 1.18
use ./hello-world
go.mod
module hello-world
go 1.18
Note: it is possible, not recommended as pointed out by #Volker
It's important that my source code remains in this src directory. It is equally important that I am able to run and build my code from the root of my project (For example the .env file is located at the root of the repository).
These two requirements are contradictory. You have to let go of one.
Especially the second one is unfounded: Do not use go run, use go build. Make the path to look for the .env file a command line option to your program (Go is not PHP or JavaScript, there simply is no project or source root for the executing binary). Or build the executable somewhere but execute it in you project root.
Note that having a src folder is -- to put it mildly -- uncommon.
I tried moving the go.mod at the root of the project and running and ran go run ./src but this causes issues of its own:
Well, start by not using go run at all, use go build. And then try building the actual main package. All the go tooling works best on packages, not on file system folders. If your module is named playing.hardball/for-unspecific-reasons and package main is in src try go build playing.hardball/for-unspecific-reasons/src.
Takeaways even if this doesn't work out the way you want:
Do not use go run. The reasons are manyfold, it is useful to run single file scripts and a loaded footgun for basically every other use case.
The go tool works on import paths. In simple cases the import path can be inferred from the filesystem.
A compiled executable has no notion of a "project directory", "source", "classpath" or whatever, it is a standalone executable runnable everywhere and completely detached from its sources.
Make all filesystem lookup path a configuration option (cmdline flag or environment variable); provide practical defaults (e.g. ./); use that when running your executable to announce where to find static stuff like .env files, templates, icons, css files, etc.

vendor directory not being used to resolve imports on go build

I'm in the process of relearning Go. I installed the latest Go version (1.7.1) using gvm and I am looking to build a simple rest api app using gin. I installed it using glide get https://github.com/gin-gonic/gin (glide) and that created a "vendor" folder on my project root. Running my app though, go run main.go, I encounter this error
main.go:3:8: cannot find package "github.com/gin-gonic/gin" in any of:
/home/yowmamasita/.gvm/gos/go1.6.3/src/github.com/gin-gonic/gin (from $GOROOT)
/home/yowmamasita/.gvm/pkgsets/go1.6.3/global/src/github.com/gin-gonic/gin (from $GOPATH)
It is not resolving the "vendor" directory glide just created
.
├── glide.lock
├── glide.yaml
├── main.go
├── README.md
└── vendor
└── github.com
└── gin-gonic
└── gin
Not sure what's happening here, I thought after 1.5, it should be able to resolve imports from "vendor" directories without doing anything. I even added my projects folder on my $GOPATH
/home/yowmamasita/.gvm/pkgsets/go1.7.1/global:/home/yowmamasita/goprojects
What am I doing wrong here? I tried 1.6.3 too and I get the same error.
Please make sure:
Add the workspace (/home/yowmamasita/goprojects) to $GOPATH variable.
Typically under workspace there will be three directories which are bin, pkg and src. More details
You can omit pkg and bin, but the project which is using vendor packages or your custom package must be placed under $GOPATH/src, otherwise go compiler will not recognized it.
More discussions can be found here and here
The structure should look like:
$GOPATH
└── src
└── YOURPROJECT1
├── source codes #1
└── vendor/
└── YOURPROJECT2
├── source codes #2
└── vendor/

How can I build a Rust library when installing a gem?

I'm building a gem with Rust and I need to know how to run the Rust compiler when installing the gem. With a C-extension, I can use mkmf to generate a Makefile. But how can I run cargo build --release?
The directory structure looks like this:
.
├── bin
│   ├── console
│   └── setup
├── CODE_OF_CONDUCT.md
├── Gemfile
├── Gemfile.lock
├── lib
│   ├── rmpd_adschedule
│   │   └── version.rb
│   └── rustgem.rb
├── LICENSE.txt
├── Rakefile
├── README.md
├── rustgem.gemspec
├── rust
│   ├── Cargo.lock
│   ├── Cargo.toml
│   └── src
│   └── lib.rs
└── spec
├── rustgem.rb
└── spec_helper.rb
I've created a Rake task to build the Rust library:
task :compile do
sh "cd #{File.dirname(__FILE__)}/rust && cargo build --release"
end
But how to run this Rake task when installing the gem? Or how to generate a suitable Makefile with mkmf? The Makefile should look like this:
all:
cd rust/ && cargo build --release
But it doesn't work if I put it into the root directory, and I don't know how to tell mkmf to generate this exact Makefile.
I found one stupid way to do this when the gem is loading:
module Rustgem
system("cd #{File.dirname(__FILE__)}/../rust && cargo build --release")
end
But this is not a good solution.
Turns out I can do this:
# rust/extconf.rb
require 'mkmf'
create_makefile 'rust/rustgem'
system("cd #{File.dirname(__FILE__)} && cargo build --release")
In this case, create_makefile will create an empty Makefile. Then make will return 0 make: Nothing to be done for 'all'. which is what we need, and then system call will do the work.
Or somewhat better:
require 'mkmf'
create_makefile 'rutgem'
File.write('Makefile', "all:\n\tcargo build --release\nclean:\n\trm -rf target\ninstall: ;")
I'm not sure if this is good solution. If you know a better one please tell it.
UPDATE
Actually, you can put Makefile along with empty extconf.rb in the same directory and it will work. Blog post about Ruby-Rust integration: http://undefined-reference.org/2016/05/14/writing-rubygem-in-rust.html

Maven throwing could not find class error after setting up home path

I am on mac and Installed maven using the brew install maven command. The maven was installed in /usr/local/Cellar/maven/3.3.9 path. Then i edited my ~/.bash_profile file and put the following entries
export M2_HOME="/usr/local/Cellar/maven/3.3.9"
export PATH="$PATH:$M2_HOME/bin"
now when i try mvn -version maven throws the error that
Error: Could not find or load main class org.codehaus.plexus.classworlds.launcher.Launcher
Did i configure it wrong ?
EDIT: Maven folder
$ tree -L 2 $M2_HOME
/usr/local/Cellar/maven/3.3.9
├── INSTALL_RECEIPT.json
├── LICENSE
├── NOTICE
├── README.txt
├── bin
│   ├── mvn
│   ├── mvn.cmd
│   ├── mvnDebug
│   ├── mvnDebug.cmd
│   └── mvnyjp
└── libexec
├── bin
├── boot
├── conf
└── lib
I have also seen as an option:
Create a file ~/.MacOSX/environment.plist with:
{
"M2_HOME" = "/usr/local/Cellar/maven/3.3.9/libexec";
"M2" = "/usr/local/Cellar/maven/3.3.9/libexec/bin";
}
and restart / log back in. This would make tools like IntelliJ also pick it up.
However in my case, I found some other setup script had installed an export for M2_HOME in my .profile which broke the maven install.

cfx xpi command deleting compressed files in addon /lib directory?

I have a weird problem when trying to package a Firefox add-on built using version 1.9 of the SDK. The extensions directory structure is something like this:
├── data
│   ├── file1.js
│   ├── file2.js
│   ├── jquery.min.js
│   └── uri.js
├── lib
│   ├── file3.js
│   ├── main.js
│   ├── services
│   │   ├── file4.js
│   │   ├── file5.js
│   │   └── file6.js
│   └── uri.js
├── package.json
└── package.json.backup
As part of the build process, I am running the data and 'lib` directories through uglify.js. This appears to work fine. Basically I copy the codebase to a different location, run it through uglify and I get the same directory structure except the JS files are compressed.
Next, I run cfx xpi --pkgdir=path/to/ugly/codebase to package the code into an xpi.
If I then move the produced .xpi to a new directory, unzip it with unzip and inspect the contents, most of my lib directory has been deleted. Files in the data directory are fine.
tree resources/addon_name
resources/addon_name
├── data
│   ├── file1.js
│   ├── file2.js
│   ├── jquery.min.js
│   └── uri.js
└── lib
└── main.js
If I don't uglify the JS files then everything seems to work fine and when I unzip the xpi I will have a full lib directory as I would expect.
Note that this is not a problem with the uglifying process (that was the first thing I checked). When I copy the codebase and uglify it, I can stop the process at that point and list the lib directory. It will contain all the uglified JS files I would expect. It's only after packaging and subsequent unzipping that they are gone.
I have tried reproducing this issue with a brand new extension but I get a slightly different problem. Basically, files in the lib directory are deleted on packaging regardless of whether they are compressed or not. Basically my steps are:
mkdir test_extension
cd test_extension && cfx init
touch lib/uri.js // this is
cd .. && cfx xpi pkgdir=test_extension // Have to run this part twice to get ID
mkdir unpack && mv test_textension.xpi unpack
cd unpack
unzip test_extension.xpi
ls resources/test_extension/lib
=> main.js // the uri.js file is missing
If lib/uri.js is not required from any js file of your add-on, it will
be removed from the final XPI. So if you have require('./uri.js') in
your main.js, the file should be there after the packaging.
My guessing is that uglifying the libraries makes
impossible for the current cfx tool generates the proper manifest with
all dependencies. See Manifest Generation.
Note original post on mozilla-labs-jetpack mailing list, copied the answer here to be useful to someone else that doesn't know the ML.

Resources