How to integrate Imebra v5 to a swift command line project - swift

I'm trying to import Imebra into a basic swift 5 command line project using Xcode 12. I followed the official steps but I failed. I can summarise the whole structure:
The structure of the project is just
./
├── main.swift
├── Data
└── DX_0.dcm
├── Imebra
└── CMakeLists.txt
└── docs
└── examples
└── library
└── test
└── wrappers
└── build_imebra_macos
The main swift file is
// main.swift
import Foundation
print("Hello, Imebra!")
do {
let pDataSet = try ImebraCodecFactory.load(fromFile: "PathToDicomFileFromExecutable")
let pImage = try pDataSet.getImageApplyModalityTransform(0)
print("The image width is", pImage.width)
} catch {
print(error)
}
Following the documentation, I compile the library by going to the build_imebra_macos folder and running
build_imebra_macos % cmake -GXcode -DCMAKE_BUILD_TYPE=Release ..
build_imebra_macos % cmake --build . --config Release
The build is successful and the new folder Release has the dynamic library. Now in Xcode project of the CL Swift application, SwiftyImebra.xcodeproj, I followed the next instruction "open the target Build Settings and under “Swift Compiler/ObjectiveC Bridging Header” specify the path to imebra_location/wrappers/objectivec/include/imebraobjc/imebra.h.”, with Imebra_location changed to Imebra.
Then when I build I get the error
Showing All Messages
Undefined symbol: _OBJC_CLASS_$_ImebraCodecFactory
I'm new in Swift and I guess I need to specify somewhere in Xcode where the source or the dynamic library is. However, I am not sure about this either as we have generated a cpp dynamic library so this can only interact with objective-C (?). I apologise if this is a basic question...
In addition, I'd like to learn how to use Imebra as a static library with swift.

The imebra dynamic library must be added to the project.
Drag the imebra.dylib (generated into your build folder build_imebra_macos) into your project.
Additionally, specify the folder containing the dylib into the "Library search path" in the compiler options.

Related

Building a package with generated Python files

Problem statement
When building a Python package I want the build tool to automatically execute the steps to generate the necessary Python files and include them in the package.
Here are some details about the project:
the project repository contains only the hand-written Python and YAML files
to have a fully functional package the YAML files must be compiled into Python scripts
once the Python files are generated from YAMLs, the program needed to compile them is no longer necessary (build dependency).
the hand-written and generated Python files are then packaged together.
The package would then be uploaded to PyPI.
I want to achieve the following:
When the user installs the package from PyPI, all necessary files required for the package to function are included and it is not necessary to perform any compile steps
When the user checks-out the repository and builds the package with python -m build . --wheel, the YAML files are automatically compiled into Python and included in the package. Compiler is required.
When the user checks-out the repository and installs the package from source, the YAML files are automatically compiled into Python and installed. Compiler is required.
(nice to have) When the user checks-out the repository and installs in editable mode, the YAML files are compiled into Python. The user is free to make modifications to both generated and hand-written Python files. Compiler is required.
I have a repository with the following layout:
├── <project>
│ └── <project>
│ ├── __init__.py
│ ├── hand_written.py
│ └── specs
│ └── file.ksc (YAML file)
└── pyproject.toml
And the functional package should look something like this
├── <project>
│ └── <project>
│ ├── __init__.py
│ ├── hand_written.py
│ └── generated
│ └── file.py
├── pyproject.toml
└── <other package metadata>
How can I achieve those goals?
What I have so far
As I am very fresh to Python packaging, I have been struggling to understand the relations between the pyproject.toml, setup.cfg and setup.py and how I can use them to achieve the goals I have outlined above. So far I have a pyproject.toml with the following content:
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "<package>"
version = "xyz"
description = "<description>"
authors = [ <authors> ]
dependencies = [
"kaitaistruct",
]
From reading the setuptools documentation, I understand that there are the build commands, such as:
build_py -- simply copies Python files into the package (no compiling; works differently in editable mode)
build_ext -- builds C/C++ modules (not relevant here?)
I suppose adding the compile steps for the YAML files will involve writing a setup.py file and overwriting a command, but I don't know if this is the right approach, whether it will even work, or if there are better methods, such as using a different build backend.
Alternative approaches
A possible alternative approach would be to manually compile the YAML files prior to starting the installation or build of the package.

Create a Swift framework with submodules

I have an Xcode project with a main app and a Swift Framework called Networking. Now I'd like to split that Networking module into a submodule with only some utility classes so that they are available to the main app only when explicitly imported. So the usage I'd like to achieve would be
import Networking
import Networking.Utils
// Public class in Networking
MyNetworking.doStuff()
// Public class in Networking.Utils
// Should not compile unless Networking.Utils is imported
MyNetworkingUtils.doSomething()
So my module has the following file structure
.
├── Core
│   ├── MyNetworking.swift
│   └── Networking.h
├── Info.plist
├── Utils
│   ├── NetworkingUtils.h
│   └── Utils.swift
└── module.modulemap
I created a custom module.modulemap with this content:
framework module Networking {
umbrella header "Networking.h"
export *
module * { export * }
explicit module Utils {
header "NetworkingUtils.h"
}
}
This creates the Networking module but the problem is that the Utils classes are available in the main Networking module.
The question is, how can I specify in the module map which Swift files (ideally subfolders) belong to which module.
The Networking has only Swift files so the umbrella .h files are basically empty.
It looks like it's good option here to have two different modules: Networking and NetworkingUtils (second could have dependency to first).

How to reuse code from the main bin in another bin?

My project structure looks like this:
.
├── Cargo.lock
├── Cargo.toml
└── src
├── bin
│   └── other.rs
├── main.rs
└── util.rs
(code: https://gitlab.com/msrd0/cargo-bin-import)
In my other.rs, I'm trying to reuse code from the util mod, which is declared as a public mod in my main.rs file. I tried the following:
use util::do_sth
use crate::util::do_sth
use cargo_bin_import::util::do_sth (with and without extern crate)
mod util; use util::do_sth
extern crate util; use util::do_sth (suggested by rustc)
None of the above worked and gave me error messages similar to this one:
error[E0432]: unresolved import `crate::util`
--> src/bin/other.rs:1:12
|
1 | use crate::util::do_sth;
| ^^^^ maybe a missing `extern crate util;`?
error: aborting due to previous error
Use a library and two binaries, then reuse the lib's code in the two binaries. Example:
Cargo.toml
[lib]
name = "utils"
path = "src/utils.rs"
# cargo build --bin other
[[bin]]
name = "other"
path = "src/bin/other.rs"
# cargo build --bin main
[[bin]]
name = "main"
path = "src/main.rs"
Then use utils::{...}. The path are taken from your question, but putting main inside bin/ and renaming utils.rs to lib.rs could be a more standard way to do it.
If the library is generic enough, you could even release it on crates.io for others to benefit from it.

Testing an executable with Swift

I created an executable with Swift via swift package init --type executable and would now like to write a few tests for it. This doesn't appear to be an issue at all for library packages, in that case Swift also populates the Tests directory with a tests module which runs nicely via swift test. For an executable only an empty Tests directory is created.
On trying to run tests for my executable from within Xcode or via swift test I'm running into linker issues though that seem to specify that Swift is unable to link the contents of my main.swift to the tests. I'm not sure what I can do here. I've tried playing around within Xcode to create new framework targets to be linked, but none of that would be picked up by swift test anyways as far as I can tell. I didn't manage to get it working via Xcode either. The following is the output from swift test.
Compile Swift Module 'swifttest' (1 sources)
Linking ./.build/debug/swifttest
Compile Swift Module 'swifttestTests' (1 sources)
Linking ./.build/debug/swifttestPackageTests.xctest/Contents/MacOS/swifttestPackageTests
Undefined symbols for architecture x86_64:
"__TF9swifttest3fooFT_SS", referenced from:
__TFFC14swifttestTests14SwifttestTests7testFooFT_T_u0_KzT_SS in swifttestTests.swift.o
ld: symbol(s) not found for architecture x86_64
<unknown>:0: error: link command failed with exit code 1 (use -v to see invocation)
<unknown>:0: error: build had 1 command failures
error: exit(1): /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-build-tool -f /Users/kilian/Desktop/swifttest/.build/debug.yaml test
These are the contents of my files for reference. It's a minimal example project.
main.swift
public func foo() -> String {
return "bar"
}
print(foo())
swifttestTests.swift
import Foundation
import XCTest
import swifttest
class SwifttestTests: XCTestCase {
func testFoo() {
XCTAssertEqual("bar", foo())
}
}
Directory Layout
.
├── Package.swift
├── Sources
│   └── main.swift
└── Tests
└── swifttestTests
└── swifttestTests.swift
Whilst not exactly a solution to not being able to test an executable I was made aware of a workaround. The basic idea is to move more or less everything into a second module inside the same project and minimizing the executable target to a call to an entry function.
A basic structure following the given example would look like this:
.
├── Package.swift
├── Sources
│ └── swifttest
│ │ └── main.swift
│ └── SwiftTestLib
│ └── foo.swift
└── Tests
└── SwiftTestLibTests
└── SwiftTestLibTests.swift
This makes it necessary however to specify the targets in the Package.swift.
import PackageDescription
let package = Package(
name: "swifttest",
targets: [
Target(name: "swifttest", dependencies: ["SwiftTestLib"]),
Target(name: "SwiftTestLib", dependencies: []),
],
dependencies: []
)

IDEA 12 Create Scala Play 2.0: Project Files Changed

PROBLEM:
When I'm working with a Scala Play 2.0.4 application from within IntelliJ IDEA 12, I'm getting a lot of red syntax highlighting errors that don't show up as errors when I run the application from within Play! at the command line.
QUESTION:
Are there others who are successfully running Scala Play 2.0 applications from within IntelliJ IDEA 12? If so, can you give me some suggestions as to how I might do this as well.
BACKGROUND INFO:
When I create a new project within IntelliJ, I set Play 2 home to ~/bin/opt/play-2.0.4, it creates the project and then a dialog box appears titled "Project Files Changed" which says that "Project file .../.idea/misc.xml has been changed externally. It is recommended to reload project for changes to take effect." If I ignore the prompt to reload the project, and I ctl-ins on app/, I get the following options:
Java Class
Scala Class
File
Package
I then create a package 'models', and a scala file 'Models.scala' with the code shown below, 'Hello' is syntax-highlighted as red and when I hover over the code, IDEA indicates that it can't find 'Hello' within the object MyDB:
package models
case class Hello(id: Int, name: String)
object MyDB {
val hellos: List[Hello] = List(Hello(1, "Foo"), Hello(2, "Bar"))
}
I can now create create app/models/Models.scala with the code above and there are no highlighting errors. However, when I go to project settings -> Modules -> Dependencies, it says that 'sbt-and-plugins' has a broken path and "Module 'untitled': invalid item 'scala-2.9.1' in the dependencies list"
On the other hand, if I click 'ok' to reload the project for the changes to take effect, then if I I ctl-ins on app/, I get the following options:
File
Directory
This second option occurs also if I generate idea from within play at the command line (as well, with-sources), and also if I compile the project (either before or after I run idea).
As a further hint the app directory is colored blue if I don't reload the project, but once I reload it, then the app directory icon is brownish (like the others).
It is the same whether I use play-2.0.4 that I downloaded myself or whether I ask IntelliJ to download it when I create the new project. It also is the same whether I have the playframework with Play 2.0 Support or just the Play 2.0 Support by itself.
For further information, I'm running Arch Linux, Oracle Java 1.7.0_09, scala-2.9.1.final, Play 2.0.4, IntelliJ 12.0 IU-123.72. Plugins: Scala (0.6.371), Play 2.0 Support (0.1.86), Playframework Support (both with and without this, I get the same error).
UPDATE:
Here's the stacktrace http://pastebin.com/uWEpv5Gd, which shows that IDEA throws an exception when creating the project, as follows:
[ 87553] ERROR - com.intellij.ide.IdeEventQueue - Error during dispatching of java.awt.event.InvocationEvent[INVOCATION_DEFAULT,runnable=com.intellij.openapi.progress.util.ProgressWindow$MyDialog$1#3b5a26d6,notifier=null,catchExceptions=false,when=1355073846201] on sun.awt.X11.XToolkit#1bd172ba
I usually to the following to get Play projects running in IntelliJ 12:
Create the project from the terminal with play new "projectname"
Go into the new folder "projectname"
Run play idea
Open that folder with IntelliJ and enable syntax highlighting
Hope this helps
The problem was not the JVM, the problem is with the Play 2.0 plugin. I tested it with various JVMs in 1.7 and 1.6 and was still getting the same problem. I tried a fresh install of Intellij IDEA 12 by deleting the configuration directory, and it was doing the same thing. When I create a new project with IDEA 12, here's what the directory structure of target looks like:
[ambantis#okosmos target]$ tree
.
├── scala-2.9.1
│   └── cache
│   └── update
│   ├── inputs
│   └── output
└── streams
└── $global
├── ivy-configuration
│   └── $global
│   └── out
├── ivy-sbt
│   └── $global
│   └── out
├── project-descriptors
│   └── $global
│   └── out
└── update
└── $global
└── out
13 directories, 6 files
what's missing are /target/scala-2.9.1/classes and /target/scala-2.9.1/classes_managed. The solution is as follows:
After the build process, if you see a dialog box that says, "Project Files Changed", like this:
do not click OK, instead escape. Then open the play console and compile the application. At this point it will work. You will only see errors that there are unused jar files, but otherwise everything will work fine.