Unable to include multi file in the golang - struct

I know this question has been asked before and I've tried all possible answers, but nothing still didn't help me.
However to refresh the question again and to elaborate my problem. I'm actually trying to include a simple file to the main.go file. My folder structure and the rest of the information as follows:
\src\
Multi-file\
lib\Car.go
main.go
Car.go
package main
type Car struct {
numberOfDoors int
cylinders int
}
main.go
package main
import (
"fmt"
)
func main() {
c := Car{4,6}
fmt.Println(c)
}
When I complie the main.go I'm getting the following error
# command-line-arguments
.\main.go:8: undefined: Car
Here is my go env details:
set GOARCH=amd64
set GOBIN=
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=C:\xampp\htdocs\golang
set GORACE=
set GOROOT=C:\Go
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GO15VENDOREXPERIMENT=
set CC=gcc
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
set CXX=g++
set CGO_ENABLED=1
FYI: I tried including as package also that didn't even help me out.
Any help would be extremely appreciated.

Set up your workspace for programs and libraries by following the instructions: How to Write Go Code.
For your example, a two file main package,
src/car
├── car.go
└── main.go
$ cd src/car
$ go run main.go car.go
{4 6}
$ go build car && ./car
{4 6}
$ go install car && car
{4 6}
$
main.go:
package main
import (
"fmt"
)
func main() {
c := Car{4, 6}
fmt.Println(c)
}
car.go:
package main
type Car struct {
numberOfDoors int
cylinders int
}

You should not have 2 files, that are declared in the same package but are not residing in the same directory. One solution could be to have this directory structure instead:
src\
car\
car.go
main.go
car.go
package car
type Car struct {
NumberOfDoors int
Cylinders int
}
main.go
package main
import (
"car"
"fmt"
)
func main() {
c := car.Car{4, 6}
fmt.Println(c)
}
Of course, Car structure not being in main package, I had to:
change to uppercase the first letter of NumberOfDoors and Cylinders fields from car.Car struct, so that they can be accessed from main package
replace the call to Car{4,6} with car.Car{4,6}
code in car.go is not part of package main anymore, you can view it as a car library now. That's why the Car struct is now declared being part of package car
Like that, you can build and run in one step with:
go run main.go

Related

How to create a dependency bundle?

I want to create a bundle of dependencies to easily include in other cargo projects.
Say I have three different libraries: engine_logger, engine_files, engine_bench.
Is it possible to bundle them together into a dependency called engine_essentials?
#cargo.toml
#So that I can simply do:
[dependencies]
engine_essentials
#instead of:
#engine_logger = {path = "crates/engine_logger"}
#engine_files = {path = "crates/engine_files"}
#engine_bench = {path = "crates/engine_bench:}
You can create a library named engine_essentials which depends on the other three and reexports them; its source code would consist of src/lib.rs:
pub use engine_logger as logger;
pub use engine_files as files;
pub use engine_bench as bench;
Or you could reexport the contents of all three, but this risks running into name conflicts if the 3 libraries have any common module names (common, utils, prelude, that sort of thing):
pub use engine_logger::*;
pub use engine_files::*;
pub use engine_bench::*;

Python list not sorting when called from inside a bash script

I am trying to print a custom help message for a bash script. Inside the script, I call a function that then uses python to parse the script, find the functions and the function help string, and then print them. This all works. But, when I try to sort the list of tuples that contains the function name and help string, the sort seems to be ignored. Similar code works as expected in a pure python environment.
Edit: Just noticed I tried the sort two different ways. AFAIK either should have sorted the list, but neither worked.
Edit again: see the accepted answer below for code that actually works. I need to remember to reread my problem code in the morning ;)
SCRIPT_PATH=$(realpath $0)
function build() { ## builds source and wheel package
echo "foo"
}
function aa() { ## foo
echo "foo"
}
function release() { ## package and upload a release
echo "foo"
}
function project:init:all() { ## Initialize a venv, update pip, wheels, and setuptools, and install both requirements files.
echo "foo"
}
function venv:init() { ## makes a venv in the project directory
echo "foo"
}
function print:help() {
echo $SCRIPT_PATH
python3 - << EOF
from pathlib import Path
from operator import itemgetter
import re
script_path = Path("$SCRIPT_PATH")
with open(script_path) as file:
for line in file:
match = re.match(r'^function\s*([a-zA-Z0-9\:-]*)\(\)\s*{\s*##\s*(.*)', line)
matches = []
if match is not None:
target, help = match.groups()
matches.append((target,help))
#for help_line in sorted(matches,key=lambda func: func[1]):
matches.sort(key=itemgetter(1))
for help_line in matches:
print(" {0:20} {1}".format(target,help))
EOF
}
results in:
build builds source and wheel package
aa foo
release package and upload a release
project:init:all Initialize a venv, update pip, wheels, and setuptools, and install both requirements files.
venv:init makes a venv in the project directory
but I expected:
aa foo
build builds source and wheel package
project:init:all Initialize a venv, update pip, wheels, and setuptools, and install both requirements files.
release package and upload a release
venv:init makes a venv in the project directory
You need to get all the functions, then sort and print :
function print:help() {
echo $SCRIPT_PATH
python3 - << EOF
from pathlib import Path
from operator import itemgetter
import re
script_path = Path("$SCRIPT_PATH")
with open(script_path) as file:
functions = []
for line in file:
match = re.match(r'^function\s*([a-zA-Z0-9\:-]*)\(\)\s*{\s*##\s*(.*)', line)
if match is not None:
functions.append(match.groups())
for target, help in sorted(functions):
print(" {0:20} {1}".format(target,help))
EOF
}

How to use an NPM library which executes another library's bin in its code?

Here's my case: I have a project P, two libraries L1 and L2. L2 provides an executable bin in its package, which was called in L1's code using execSync function, code like:
// code in library L1
import { execSync } from 'child_process';
export function foo() {
const cmd = 'npx L2';
return execSync(cmd).toString()
}
As usual, L1 has L2 as its dependency in package.json file.
In project P, I tried to use library L1 like this.
First, use npm i L1 to install library L1;
Then, call the function foo like:
// code in project P
import { foo } from 'L1';
foo();
But I got an error like this:
Error: Cannot find module '~/project_P/node_modules/L1/node_modules/L2/index.js'
It seems that it went to a wrong place to find the L2's executable bin file. Because now L2 is in project_P/node_modules, but not in L1/node_moudules any more.
Also, I tried to change the cmd in foo like below, but none of them works.
cmd = 'PATH=$(npm bin):$PATH L2';
cmd = 'npm run L2' (having script 'L2' in package.json at the same time);
cmd = 'node ../node_modules/.bin/L2';
Does anyone have a clue how to resolve this? Any help would be greatly appreciated!

Compiling Haskell package using c++ and stack/cabal

There's a package clipper http://hackage.haskell.org/package/clipper that I want to use to detect intersection of complex polygons. It's an FFI to a C++ package. It works fine if you run
cabal build --with-gcc=/usr/bin/g++
but not otherwise. Is there some way to put that gcc option into the cabal file or otherwise get my stack project to build the dependency with g++?
Setting the $PATH for some reason doesn't work:
% cabal build --with-gcc=g++
Building clipper-0.0.1...
Preprocessing library clipper-0.0.1...
[1 of 1] Compiling Algebra.Clipper ( dist/build/Algebra/Clipper.hs, dist/build/Algebra/Clipper.o )
In-place registering clipper-0.0.1...
% PATH=$(pwd):$PATH gcc
g++: fatal error: no input files
compilation terminated.
% PATH=$(pwd):$PATH cabal build
Building clipper-0.0.1...
Preprocessing library clipper-0.0.1...
In file included from Clipper.hsc:27:0:
cbits/clipper.hpp:29:18: fatal error: vector: Dosiero aŭ dosierujo ne ekzistas
compilation terminated.
compiling dist/build/Algebra/Clipper_hsc_make.c failed (exit code 1)
command was: /usr/bin/gcc -c dist/build/Algebra/Clipper_hsc_make.c -o dist/build/Algebra/Clipper_hsc_make.o -fno-stack-protector -D__GLASGOW_HASKELL__=710 -Dlinux_BUILD_OS=1 -Dx86_64_BUILD_ARCH=1 -Dlinux_HOST_OS=1 -Dx86_64_HOST_ARCH=1 -Icbits -Idist/build/autogen -include dist/build/autogen/cabal_macros.h -I/usr/local/haskell/ghc-7.10.2-x86_64/lib/ghc-7.10.2/base_GDytRqRVSUX7zckgKqJjgw/include -I/usr/local/haskell/ghc-7.10.2-x86_64/lib/ghc-7.10.2/integ_2aU3IZNMF9a7mQ0OzsZ0dS/include -I/usr/local/haskell/ghc-7.10.2-x86_64/lib/ghc-7.10.2/include -I/usr/local/haskell/ghc-7.10.2-x86_64/lib/ghc-7.10.2/include/
Similarly, changing the Setup.hs as proposed by the #ErikR below didn't help.
% runghc Setup.hs build
"Hello, I am running"
fomg
BuildFlags
{ buildProgramPaths = []
, buildProgramArgs = []
, buildDistPref = Flag "dist"
, buildVerbosity = Flag Normal
, buildNumJobs = NoFlag
, buildArgs = []
}
fimg
BuildFlags
{ buildProgramPaths = [ ( "gcc" , "/usr/bin/g++" ) ]
, buildProgramArgs = []
, buildDistPref = Flag "dist"
, buildVerbosity = Flag Normal
, buildNumJobs = NoFlag
, buildArgs = []
}
Building clipper-0.0.1...
Preprocessing library clipper-0.0.1...
In file included from Clipper.hsc:27:0:
(etc)
Note that it crashes at the buildHook line, so in order to get the flags printed I needed to change the order around.
Try this simpler custom Setup.hs file:
import Distribution.Simple
import System.Environment
main = do
args <- getArgs
defaultMainArgs $ ["--with-gcc=c++"] ++ args
Original Answer
Some ideas:
(1) Create a wrapper script called gcc which invokes g++. Put the script early in your PATH so that running gcc will run your script instead of the real gcc. Perhaps you have this wrapper script in place only when you are building the clipper package.
(2) Write a custom Setup.hs.
Modify the build-type field in the clipper.cabal file to be Custom instead of Simple
Replace the Setup.hs file with:
import Distribution.Simple
import Distribution.Simple.Setup
import Distribution.Simple.LocalBuildInfo
import Distribution.PackageDescription
import Text.Show.Pretty
main = do
let hooks = simpleUserHooks
myBuild :: PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()
myBuild pkgd buildinfo uhooks flags = do
putStrLn $ ppShow flags
let flags' = flags { buildProgramPaths = [("gcc","g++")] ++ (buildProgramPaths flags) }
buildHook hooks pkgd buildinfo uhooks flags'
putStrLn $ ppShow flags'
hooks' = hooks { buildHook = myBuild }
defaultMainWithHooks hooks'
Note: The import of Text.Show.Pretty is not necessary, so you can remove it and the ppShow calls if you don't have it installed.
The above Setup.hs should have the same effect as calling cabal with --with-gcc=g++.

How to make interface and implementation files separately?

I would like to make interface (class, or instance) and implementation files in Haskell separately as follow:
file1: (For interface)
class X where
funcX1 = doFuncX1
funcX2 = doFuncX2
....
instance Y where
funcY1 = doFuncY1
funcY2 = doFuncY2
...
file 2: (For implementation)
doFuncX1 = ...
doFuncX2 = ...
doFuncY1 = ...
...
How can I do that when file1 must be imported in file2 and vice versa ?
You don't need any such cumbersome separation in Haskell. Just mark only what you want to be public in the module export list (module Foo ( X(..) ... ) where ...), build your project with cabal, and if you want to export a library but not release the source code you can simply publish only the dist folder with the binary interface files and the Haddock documentation. That's much more convenient than nasty e.g. .h and .cpp files that need to be kept manually in sync.
But of course, nothing prevents you from putting implementations in a seperate, non-public file. You just don't need to do "vice versa" imports for this, only perhaps a common file with the necessary data type declarations. E.g.
Public.hs:
module Public(module Public.Datatypes) where
import Public.Datatypes
import Private.Implementations
instance X Bar where { funcX1 = implFuncX1; ... }
Public/Datatypes.hs:
module Public.Datatypes where
data Bar = Bar { ... }
class X bar where { funcX1 :: ... }
Private/Implementations.hs:
module Private.Implementations(implFuncX1, ...) where
import Public.Datatypes
implFuncX1 :: ...
implFuncX1 = ...
But usually it would be better to simply put everything in Public.hs.

Resources